

#ifndef _C_GAUSS_H_
#define _C_GAUSS_H_



#include "sl_matrix.h"

/// <summary>
/// 高斯分布的矢量。用于计算样本矢量的协方差矩阵，及样本矢量在数据集中出现的概率。
/// </summary>
typedef struct _gauss_vec_
{
    //特征值与特征向量的英文是 eigenvalue 和 eigenvector
    real_t cov_det;      // 协方差矩阵的值。
    real_t sqrt_cov_det; // 协方差矩阵的值的开方。
    mat A;	        // A*AT=cov。如果随机矢量v的元素相互独立，且都满足N(0,1)的正态分布，则rand_vec = ave+A*v  
    // -> A 的行矢量是特征矢量，不过不是单位的
    mat covariance;  //协方差矩阵。
    mat icovariance;  //协方差矩阵的倒数。

    vec mean_vector; //样本中心矢量。
    int dimension;    //样本维度

    // 下面两个矢量是计算矢量概率的中间变量。
    vec temp;   //高斯分布计算的中间变量
    vec random; // 高斯分布的随机矢量。

}gauss_vec;


/// <summary>
/// 初始化数据。样本数据最好比维度高。这样协方差矩阵才满秩。
/// </summary>
/// <param name="gauss">高斯分布数据的结构体</param>
/// <param name="sample">样本数组</param>
/// <param name="sample_count">样本数量</param>
void gauss_vec_init_by_data(gauss_vec* gauss, vec sample[], int sample_count);

/// <summary>
/// 初始化数据。样本数据最好比维度高。这样协方差矩阵才满秩。
/// </summary>
/// <param name="gauss">高斯分布数据的结构体</param>
/// <param name="d">样本维度</param>
void gauss_vec_init(gauss_vec* gauss, int d);

/// <summary>
/// 释放高斯分布数据的结构体
/// </summary>
/// <param name="gauss">高斯分布数据的结构体</param>
void gauss_vec_release(gauss_vec* gauss);

/// <summary>
/// 计算矢量在数据中的概率。假设概率是高维高斯分布的。
/// </summary>
/// <param name="gauss">高斯分布数据的结构体</param>
/// <param name="v">样本矢量</param>
/// <returns>该样本矢量在数据集中出现的概率，这里的概率是概率密度，需要积分才有意义</returns>
real_t gauss_vec_probability(gauss_vec gauss, vec v);

/// <summary>
/// 刷新高斯的随机矢量。运行该函数后，刷新矢量v , gauss.random变成gauss的随机矢量
/// </summary>
/// <param name="gauss">高斯分布的结构体</param>
void gauss_vec_randomize(gauss_vec gauss);

/// <summary>
/// 高斯分布更新协方差矩阵后，调用这个函数刷新其他变量
/// </summary>
/// <param name="gauss">高斯分布数据的结构体 </param>
void gauss_vec_renew_cov(gauss_vec* gauss);









void test_Gauss(void);



#endif

